#pragma once

#include <ddm/AtomicRoute.h>
#include <ddm/if/gen-cpp2/DDM_types.h>
#include <folly/IPAddress.h>
#include <openr/common/OpenrEventBase.h>
#include <openr/if/gen-cpp2/OpenrCtrlCppAsyncClient.h>
#include <openr/messaging/ReplicateQueue.h>

#include <map>

namespace ddm {
class MapReducer : public openr::OpenrEventBase {
 public:
  MapReducer(
      openr::messaging::RQueue<AtomicRoute> atomicRouteUpdateQueue,
      openr::messaging::RQueue<ddm::thrift::Requirement> requirementsQueue,
      std::string nodeId);

 private:
  void processAtomicRouteUpdate(AtomicRoute&& atomicRoute);
  void processRequirement(ddm::thrift::Requirement&& req);
  std::map<std::string, RANGES> map(folly::CIDRNetwork prefix);
  void map1(ddm::thrift::Requirement& req);
  void transition(std::string reqName);
  void reduce(RANGES ranges);
  void reduce1();

  std::map<std::string, AtomicRoute&&> egressToAtomicRoute_;

  // The atomic routes without requirements
  std::map<std::string, RANGES> egressToRanges_;

  std::map<std::string, std::map<std::string, RANGES>> reqToAtomicRoutes_;
  std::map<std::string, std::pair<RANGES, int>> reqToTuple_;
  std::string nodeId_;
};
}  // namespace ddm